home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 April: Mac OS SDK / Dev.CD Apr 96 SDK / Dev.CD Apr 96 SDK1.toast / Development Kits (Disc 1) / OpenDoc Development Framework / ODFDev / ODF / Examples / Table / Sources / TblLink.cpp < prev    next >
Encoding:
Text File  |  1995-11-08  |  32.7 KB  |  1,005 lines  |  [TEXT/MPS ]

  1. //========================================================================================
  2. //
  3. //    File:                TblLink.cpp
  4. //    Release Version:    $ 1.0d11 $
  5. //
  6. //    Author:                Mary Boetcher
  7. //
  8. //    Copyright:    © 1993, 1995 by Apple Computer, Inc., all rights reserved.
  9. //
  10. //========================================================================================
  11.  
  12. #ifndef TBLLINK_H
  13. #include "TblLink.h"
  14. #endif
  15.  
  16. #ifndef TBLPART_H
  17. #include "TblPart.h"
  18. #endif
  19.  
  20. #ifndef TBLSEL_H
  21. #include "TblSel.h"
  22. #endif
  23.  
  24. #ifndef TBLCMDS_H
  25. #include "TblCmds.h"
  26. #endif
  27.  
  28. #ifndef TBLPROXY_H
  29. #include "TblProxy.h"
  30. #endif
  31.  
  32. #ifndef TBLFRAME_H
  33. #include "TblFrame.h"
  34. #endif
  35.  
  36. // ----- Framework Includes -----
  37.  
  38. #ifndef FWPART_H
  39. #include "FWPart.h"
  40. #endif
  41.  
  42. #ifndef FWFRAME_H
  43. #include "FWFrame.h"
  44. #endif
  45.  
  46. #ifndef FWITERS_H
  47. #include "FWIters.h"
  48. #endif
  49.  
  50. #ifndef FWPRESEN_H
  51. #include "FWPresen.h"
  52. #endif
  53.  
  54. #ifndef FWSELECT_H
  55. #include "FWSelect.h"
  56. #endif
  57.  
  58. // for FW_CCloneInfo
  59. #ifndef FWPROXY_H
  60. #include "FWProxy.h"
  61. #endif
  62.  
  63. // for FW_SUForceFocus
  64. #ifndef FWUTIL_H
  65. #include "FWUtil.h"
  66. #endif
  67.  
  68. #ifndef FWPXYFRM_H
  69. #include "FWPxyFrm.h"
  70. #endif
  71.  
  72. #ifndef FWPRTITE_H
  73. #include "FWPrtIte.h"
  74. #endif
  75.  
  76. #ifndef FWUTIL_H
  77. #include "FWUtil.h"
  78. #endif
  79.  
  80. #ifndef FWCLNINF_H
  81. #include "FWClnInf.h"
  82. #endif
  83.  
  84. // ----- OS Includes -----
  85.  
  86. #ifndef FWODEXCE_H
  87. #include "FWODExce.h"
  88. #endif
  89.  
  90. #ifndef FWBARRAY_H
  91. #include "FWBArray.h"
  92. #endif
  93.  
  94. // ----- Foundation Includes -----
  95.  
  96. #ifndef FWMEMMGR_H
  97. #include "FWMemMgr.h"
  98. #endif
  99.  
  100. // ----- OpenDoc Includes -----
  101.  
  102. #ifndef SOM_Module_OpenDoc_StdProps_defined
  103. #include <StdProps.xh>
  104. #endif
  105.  
  106. #ifndef SOM_Module_OpenDoc_StdTypes_defined
  107. #include <StdTypes.xh>
  108. #endif
  109.  
  110. #ifndef SOM_ODStorageUnit_xh
  111. #include <StorageU.xh>
  112. #endif
  113.  
  114. #ifndef SOM_ODStorageUnitView_xh
  115. #include <SUView.xh>
  116. #endif
  117.  
  118. #ifndef SOM_ODLink_xh
  119. #include <Link.xh>
  120. #endif
  121.  
  122. #ifndef SOM_ODLinkSpec_xh
  123. #include <LinkSpec.xh>
  124. #endif
  125.  
  126. #ifndef SOM_ODLinkSource_xh
  127. #include <LinkSrc.xh>
  128. #endif
  129.  
  130. #ifndef SOM_ODSession_xh
  131. #include <ODSessn.xh>
  132. #endif
  133.  
  134. //========================================================================================
  135. // Runtime Information
  136. //========================================================================================
  137.  
  138. FW_DEFINE_CLASS_M1(CTablePublishLink, FW_CPublishLink)
  139. FW_DEFINE_CLASS_M1(CTableSubscribeLink, FW_CSubscribeLink)
  140. FW_DEFINE_CLASS_M1(CTableLinkManager, FW_CLinkManager)
  141.  
  142. #ifdef FW_BUILD_MAC
  143. #pragma segment opftable
  144. #endif
  145.  
  146. //========================================================================================
  147. // Constants
  148. //========================================================================================
  149.  
  150. const ODValueType kTableLinkValue = "Table:Value";
  151.  
  152. const ODPropertyName kODPropSourceLink    = "Table:Property:SourceLink";
  153. const ODPropertyName kODPropDestLink    = "Table:Property:DestLink";
  154.  
  155. //========================================================================================
  156. //    class CTablePublishLink
  157. //========================================================================================
  158.  
  159. //----------------------------------------------------------------------------------------
  160. //    CTablePublishLink constructor
  161. //----------------------------------------------------------------------------------------
  162.  
  163. CTablePublishLink::CTablePublishLink(Environment *ev, ODUpdateID changeID, 
  164.                                      FW_CPresentation* presentation,
  165.                                      CTablePart* part,
  166.                                      CTableSelection* selection) :
  167.     FW_CPublishLink(ev, changeID, presentation),
  168.     fTablePart(part),
  169.     fTableSelection(selection),
  170.     fLinkCell(selection->GetCell())
  171. {
  172. }
  173.  
  174. //----------------------------------------------------------------------------------------
  175. //    CTablePublishLink destructor
  176. //----------------------------------------------------------------------------------------
  177.  
  178. CTablePublishLink::~CTablePublishLink()
  179. {
  180. }
  181.  
  182. //----------------------------------------------------------------------------------------
  183. //    CTablePublishLink::Publish
  184. //----------------------------------------------------------------------------------------
  185.  
  186. void CTablePublishLink::Publish(Environment* ev)
  187. {
  188.     FW_ASSERT(fODLinkSource != NULL);
  189.     fODLinkSource->SetSourcePart(ev, fTablePart->GetODPart(ev)->GetStorageUnit(ev));
  190.  
  191.     //---- Change the link status of affected embedded frames
  192.     fTablePart->ChangeFrameStatus(ev, fLinkCell, kODInLinkSource);
  193.  
  194.     //--- Force the first update using a new change ID
  195.     ODUpdateID change = fTablePart->GetSession(ev)->UniqueUpdateID(ev);
  196.     this->ContentUpdated(ev, change, TRUE);    
  197. }
  198.  
  199. //----------------------------------------------------------------------------------------
  200. //    CTablePublishLink::Externalize
  201. //----------------------------------------------------------------------------------------
  202.  
  203. void CTablePublishLink::Externalize(Environment* ev, ODStorageUnit* storageUnit,
  204.                                     FW_CCloneInfo* cloneInfo)
  205. {
  206.     //-- Storage unit must be focussed to property kODPropDestLink, value kTableLinkValue
  207.     ODStorageUnitRef suRef;
  208.     fODLinkSource->Externalize(ev);
  209.  
  210.     ODID linkID = fODLinkSource->GetID(ev);
  211.     if (cloneInfo != NULL)
  212.     {
  213.         linkID = cloneInfo->Clone(ev, linkID, 0, 0);
  214.     }
  215.     FW_ASSERT(linkID != kODNULL);
  216.  
  217.     storageUnit->GetStrongStorageUnitRef(ev, linkID, suRef);
  218.     FW_CByteArray byteArray(&suRef, sizeof(ODStorageUnitRef));
  219.     storageUnit->SetValue(ev, byteArray);
  220.     byteArray.Set(&fUpdateID, sizeof(ODUpdateID));
  221.     storageUnit->SetValue(ev, byteArray);
  222.  
  223.     //-- Write out data specific to this part's publisher --
  224.     CCell cell = fLinkCell;            // table cell associated with this publisher
  225.     byteArray.Set(&cell, sizeof(CCell));
  226.     storageUnit->SetValue(ev, byteArray);
  227. }
  228.  
  229. //----------------------------------------------------------------------------------------
  230. //    CTablePublishLink::ExternalizeLinkContent
  231. //----------------------------------------------------------------------------------------
  232.  
  233. void CTablePublishLink::ExternalizeLinkContent(Environment* ev, ODStorageUnit* linkSU)
  234. {
  235.     // Remove any properties which  FW_CEmbeddingSelection::DoExternalizeSingleEmbeddedFrame 
  236.     // expects to find missing.  
  237.     // ODLinkSource::Clear removed only the content property.
  238.     FW_SURemoveProperty(ev, linkSU, kODPropContentFrame);
  239.  
  240.     // -- Pick a frame, any frame --
  241.     FW_CPresentationFrameIterator piter(fPresentation);
  242.     FW_CFrame* frame = piter.First();
  243.     FW_ASSERT(frame);
  244.  
  245.     // Since FW_CFrame::PrivHandleExternalizeScrap writes the current selection,
  246.     // we need to temporarily select our link cell
  247.     CCell savedCell = fTableSelection->GetCell();
  248.     fTableSelection->Select(ev, fLinkCell, FALSE);
  249.  
  250.     fTableSelection->ExternalizeData(ev, frame, FW_kLinkStorage, linkSU, kODCloneToLink);
  251.  
  252.     // Restore the saved selection
  253.     fTableSelection->Select(ev, savedCell, FALSE);
  254. }
  255.  
  256. //----------------------------------------------------------------------------------------
  257. //    CTablePublishLink::GetFrameToRevealLink
  258. //----------------------------------------------------------------------------------------
  259. FW_CFrame* CTablePublishLink::GetFrameToRevealLink(Environment* ev)
  260. {
  261.     // By default, return the presentation's first display frame
  262.     FW_CPresentationFrameIterator piter(fPresentation);
  263.     return piter.First();
  264. }
  265.  
  266. //----------------------------------------------------------------------------------------
  267. //    CTablePublishLink::DoSelect
  268. //----------------------------------------------------------------------------------------
  269. void CTablePublishLink::DoSelect(Environment* ev, FW_CFrame* /*frame*/)
  270. {
  271.     fTableSelection->Select(ev, fLinkCell, TRUE);    // drawNow = TRUE
  272. }
  273.  
  274. //----------------------------------------------------------------------------------------
  275. //    CTablePublishLink::HasEmbeddedFrame
  276. //---------------------------------------------------------------------------------------
  277. FW_Boolean CTablePublishLink::HasEmbeddedFrame(Environment *ev, ODFrame* odFrame)
  278. {
  279.     // Is odFrame involved in this link source? (called by Part::EmbeddedFrameChanged)
  280.  
  281.     FW_Boolean result = FALSE;
  282.  
  283.     // --- Find out whether odFrame is involved in any link source ---
  284.     if (odFrame->GetLinkStatus(ev) == kODInLinkSource)
  285.     {
  286.         // -- Find out whether odFrame is one of my frames --
  287.         FW_CFrame* fwFrame = FW_CFrame::ODtoFWFrame(ev, odFrame);
  288.         if (fwFrame)
  289.         {
  290.             CTableProxy* proxy = fTablePart->CellToProxy(ev, fLinkCell);
  291.             FW_CProxyProxyFrameIterator iter((FW_MProxy*) proxy);
  292.             for (FW_CProxyFrame* proxyFrame = iter.First(); iter.IsNotComplete(); proxyFrame = iter.Next())
  293.                 if (proxyFrame->GetFrame(ev) == odFrame)
  294.                 {
  295.                     result = TRUE;
  296.                     break;
  297.                 }
  298.         }
  299.     }
  300.  
  301.     return result;
  302. }
  303.  
  304. //----------------------------------------------------------------------------------------
  305. // CTablePublishLink::DoLinkInfo
  306. //----------------------------------------------------------------------------------------
  307. CBreakLinkSourceCommand* CTablePublishLink::DoLinkInfo(Environment* ev, ODFacet* facet)
  308. {
  309.     CBreakLinkSourceCommand* cmd = NULL;
  310.     ODLinkInfoResult infoResult;
  311.  
  312.     if (fODLinkSource->ShowLinkSourceInfo(ev, facet, fODLinkSource->GetUpdateID(ev), TRUE, &infoResult))
  313.     {
  314.         switch (infoResult.action)
  315.         {
  316.             case kODLinkInfoBreakLink:
  317.               {
  318.                 // Create and return an undoable command to break the link
  319.                 FW_CFrame* frame = FW_CFrame::ODtoFWFrame(ev, facet->GetFrame(ev));
  320.                 cmd = FW_NEW(CBreakLinkSourceCommand, (ev, frame, this)); 
  321.               }
  322.                 break;
  323.             case kODLinkInfoUpdateNow:
  324.                 this->ContentUpdated(ev, fUpdateID, TRUE);
  325.                 break;
  326.             case kODLinkInfoOk:
  327.                 if (infoResult.autoUpdate != fODLinkSource->IsAutoUpdate(ev))
  328.                 {
  329.                     fODLinkSource->SetAutoUpdate(ev, infoResult.autoUpdate);
  330.                     if (infoResult.autoUpdate)
  331.                         if (fUpdateID != fODLinkSource->GetUpdateID(ev))
  332.                             // changed from manual to automatic updates, and
  333.                             // the link is out of date-- update it now
  334.                             this->ContentUpdated(ev, fODLinkSource->GetUpdateID(ev), TRUE);
  335.                 }
  336.                 break;
  337.         }
  338.     }
  339.  
  340.     return cmd;    // cmd is non-NULL if user said to break the link
  341. }
  342.  
  343. //----------------------------------------------------------------------------------------
  344. // CTablePublishLink::BreakLink
  345. //----------------------------------------------------------------------------------------
  346. void CTablePublishLink::BreakLink(Environment* ev)
  347. {
  348.     FW_CPublishLink::BreakLink(ev);
  349.  
  350.     //--- Erase Link Borders ---
  351.     fPresentation->Invalidate(ev);    // force all frames to be redrawn
  352.  
  353.     //--- Change status of embedded frames ---
  354.     fTablePart->ChangeFrameStatus(ev, fLinkCell, kODNotInLink);
  355. }
  356.  
  357. //========================================================================================
  358. //    class CTableSubscribeLink
  359. //========================================================================================
  360.  
  361. //----------------------------------------------------------------------------------------
  362. //    CTableSubscribeLink constructor
  363. //----------------------------------------------------------------------------------------
  364.  
  365. CTableSubscribeLink::CTableSubscribeLink(Environment* ev, 
  366.                                          ODLink* odLink,
  367.                                          ODLinkInfo* linkInfo, 
  368.                                          FW_CPresentation* presentation,
  369.                                          CTablePart* part,
  370.                                          CTableSelection* selection) :
  371.     FW_CSubscribeLink(ev, odLink, linkInfo, presentation),
  372.     fTablePart(part),
  373.     fTableSelection(selection),
  374.     fLinkCell(selection->GetCell())
  375. {
  376. }
  377.  
  378. //----------------------------------------------------------------------------------------
  379. //    CTableSubscribeLink destructor
  380. //----------------------------------------------------------------------------------------
  381.  
  382. CTableSubscribeLink::~CTableSubscribeLink()
  383. {
  384. }
  385.  
  386. //----------------------------------------------------------------------------------------
  387. //    CTableSubscribeLink::Subscribe
  388. //----------------------------------------------------------------------------------------
  389.  
  390. void CTableSubscribeLink::Subscribe(Environment* ev)
  391. {
  392.     fTablePart->ChangeFrameStatus(ev, fLinkCell, kODInLinkDestination);
  393. }
  394.  
  395. //----------------------------------------------------------------------------------------
  396. //    CTableSubscribeLink::DoUpdateLink
  397. //--------------------------------------------------------------------
  398. void CTableSubscribeLink::DoUpdateLink(Environment* ev, ODStorageUnit* linkContentSU)
  399. {
  400.     FW_CPresentationFrameIterator piter(fPresentation);
  401.     FW_CFrame* frame = piter.First();
  402.     FW_ASSERT(frame);
  403.  
  404.     // Since CTableFrame::EmbedSingleFrame embeds into the selected cell,
  405.     // we need to temporarily select our link cell
  406.     CCell savedCell = fTableSelection->GetCell();
  407.     fTableSelection->Select(ev, fLinkCell, FALSE);
  408.  
  409.     //-- Read data from the linkContentSU --
  410.     fTableSelection->InternalizeData(ev, frame, linkContentSU, kODCloneFromLink);
  411.  
  412.     //-- Restore the previous selection
  413.     fTableSelection->Select(ev, savedCell, FALSE);
  414.  
  415.     fPresentation->Invalidate(ev);    // force all frames to be redrawn
  416. }
  417.  
  418. //----------------------------------------------------------------------------------------
  419. // CTableSubscribeLink::DoLinkInfo
  420. //----------------------------------------------------------------------------------------
  421. CBreakLinkCommand* CTableSubscribeLink::DoLinkInfo(Environment* ev, ODFacet* facet)
  422. {
  423.     CBreakLinkCommand* cmd = NULL;
  424.     ODLinkInfoResult infoResult;
  425.         
  426.     if (fODLink->ShowLinkDestinationInfo(ev, facet, &fLinkInfo, TRUE, &infoResult))
  427.     {
  428.         switch (infoResult.action)
  429.         {
  430.             case kODLinkInfoFindSource:
  431.                 fODLink->ShowSourceContent(ev);
  432.                 break;
  433.             case kODLinkInfoBreakLink: 
  434.               {
  435.                 // Create and return an undoable command to break the link
  436.                 FW_CFrame* frame = FW_CFrame::ODtoFWFrame(ev, facet->GetFrame(ev));
  437.                 cmd = FW_NEW(CBreakLinkCommand, (ev, frame, this)); 
  438.               }
  439.                 break;
  440.             case kODLinkInfoUpdateNow:
  441.                 this->LinkUpdated(ev, fODLink->GetUpdateID(ev));
  442.                 break;
  443.             case kODLinkInfoOk:
  444.                 if (infoResult.autoUpdate != fLinkInfo.autoUpdate)
  445.                 {
  446.                     fLinkInfo.autoUpdate = infoResult.autoUpdate;
  447.                     this->Register(ev, fTablePart);
  448.                 }
  449.                 break;
  450.         }
  451.     }
  452.  
  453.     return cmd;    // cmd is non-NULL if user said to break the link
  454. }
  455.  
  456. //----------------------------------------------------------------------------------------
  457. // CTableSubscribeLink::BreakLink
  458. //----------------------------------------------------------------------------------------
  459. void CTableSubscribeLink::BreakLink(Environment* ev)
  460. {
  461.     FW_CSubscribeLink::BreakLink(ev);
  462.  
  463.     //--- Erase Link Borders ---
  464.     fPresentation->Invalidate(ev);    // force all frames to be redrawn
  465.  
  466.     //--- Change status of embedded frames ---
  467.     fTablePart->ChangeFrameStatus(ev, fLinkCell, kODNotInLink);
  468. }
  469.  
  470. //----------------------------------------------------------------------------------------
  471. //    CTableSubscribeLink::Externalize
  472. //----------------------------------------------------------------------------------------
  473.  
  474. void CTableSubscribeLink::Externalize(Environment* ev, ODStorageUnit* storageUnit,
  475.                                       FW_CCloneInfo* cloneInfo)
  476. {
  477.     //-- Storage unit must be focussed to property kODPropDestLink, value kTableLinkValue
  478.     ODStorageUnitRef suRef;
  479.     fODLink->Externalize(ev);
  480.  
  481.     ODID linkID = fODLink->GetID(ev);
  482.     if (cloneInfo != NULL)
  483.     {
  484.         linkID = cloneInfo->Clone(ev, linkID, 0, 0);
  485.     }
  486.     FW_ASSERT(linkID != kODNULL);
  487.  
  488.     storageUnit->GetStrongStorageUnitRef(ev, linkID, suRef);
  489.     FW_CByteArray byteArray(&suRef, sizeof(ODStorageUnitRef));
  490.     storageUnit->SetValue(ev, byteArray);
  491.  
  492.     ODType kind = fLinkInfo.kind;            // save kind string
  493.     fLinkInfo.kind = (ODType) strlen(kind) + 1;
  494.     byteArray.Set(&fLinkInfo, sizeof(ODLinkInfo));
  495.     storageUnit->SetValue(ev, byteArray);    // write out linkinfo
  496.     byteArray.Set((void*)kind, (ODULong)fLinkInfo.kind);
  497.     storageUnit->SetValue(ev, byteArray);    // write out kind string
  498.     fLinkInfo.kind = kind;                    // restore kind string
  499.  
  500.     // Write out data specific to this part's subscriber
  501.     CCell cell = fLinkCell;                // table cell associated with this link
  502.     byteArray.Set(&cell, sizeof(CCell));
  503.     storageUnit->SetValue(ev, byteArray);
  504. }
  505.  
  506. //========================================================================================
  507. //    class CTableLinkManager
  508. //========================================================================================
  509.  
  510. //----------------------------------------------------------------------------------------
  511. //    CTableLinkManager constructor
  512. //----------------------------------------------------------------------------------------
  513.  
  514. CTableLinkManager::CTableLinkManager(Environment* ev, CTablePart* thePart) :
  515.     FW_CLinkManager(ev, (FW_CPart*)thePart),
  516.     fTablePart(thePart)
  517. {
  518. }
  519.  
  520. //----------------------------------------------------------------------------------------
  521. //    CTableLinkManager destructor
  522. //----------------------------------------------------------------------------------------
  523.  
  524. CTableLinkManager::~CTableLinkManager()
  525. {
  526. }
  527.  
  528. //----------------------------------------------------------------------------------------
  529. //    CTableLinkManager::NewPublishLink
  530. //----------------------------------------------------------------------------------------
  531.  
  532. FW_CPublishLink* CTableLinkManager::NewPublishLink(Environment* ev, ODUpdateID changeID, 
  533.                                                     FW_CPresentation* presentation)
  534. {
  535.     return new CTablePublishLink(ev, changeID, presentation, fTablePart, fTablePart->GetTableSelection(ev));
  536. }
  537.  
  538. //----------------------------------------------------------------------------------------
  539. //    CTableLinkManager::NewSubscribeLink
  540. //----------------------------------------------------------------------------------------
  541.  
  542. FW_CSubscribeLink* CTableLinkManager::NewSubscribeLink(Environment* ev, ODLink *odLink,
  543.                                                         ODLinkInfo* linkInfo,
  544.                                                         FW_CPresentation* presentation)
  545. {
  546.     return new CTableSubscribeLink(ev, odLink, linkInfo, presentation, fTablePart, fTablePart->GetTableSelection(ev));
  547. }
  548.  
  549. //----------------------------------------------------------------------------------------
  550. //    CTableLinkManager::DoChangeLinkStatus
  551. //----------------------------------------------------------------------------------------
  552.  
  553. void CTableLinkManager::DoChangeLinkStatus(Environment* ev, ODFrame* odFrame)
  554. {
  555.     // call ODFrame::ChangeLinkStatus on any embedded frames that are involved in a link
  556.     // when a link is created, broken, moved, etc.
  557.     // odFrame is the frame of this part whose link status has changed.
  558.     
  559.     FW_CEmbeddingFrame* frame = FW_CEmbeddingFrame::ODtoFWEmbeddingFrame(ev, odFrame);
  560.     if (frame)
  561.     {
  562.         ODLinkStatus linkStatus = odFrame->GetLinkStatus(ev);
  563.  
  564.         // Only need to propagate linkStatus to embedded frames that don't participate in
  565.         // any of this part's links; otherwise their local link status takes precedence.
  566.  
  567.         FW_COrderedCollectionIterator iter(fTablePart->fProxys);
  568.         for (CTableProxy* proxy = (CTableProxy*)iter.First(); iter.IsNotComplete(); proxy = (CTableProxy*)iter.Next())
  569.         {
  570.             if (!this->IsCellInLink(ev, proxy->GetCell()))
  571.             {
  572.                 FW_CProxyEmbeddedFrameIterator efiter(ev, proxy);
  573.                 for (ODFrame* embFrame = efiter.First(ev); efiter.IsNotComplete(ev); embFrame = efiter.Next(ev))
  574.                     embFrame->ChangeLinkStatus(ev, linkStatus);
  575.             }
  576.         }
  577.     }
  578. }
  579.  
  580. //----------------------------------------------------------------------------------------
  581. //    CTableLinkManager::DoUpdateLinks
  582. //----------------------------------------------------------------------------------------
  583.  
  584. void CTableLinkManager::DoUpdateLinks(Environment* ev, ODFrame* odEmbeddedFrame, ODUpdateID change)
  585. {
  586.     // Content displayed in the embedded frame has changed
  587.  
  588.     /* 1) If odEmbeddedFrame is involved in one of my link sources, update the link with new data.
  589.           "If the part maintains the source of a link that includes the embedded frame, the
  590.           part should update the link." (Recipe p.12) */
  591.     if (this->CountPublishers(ev) > 0)
  592.     {
  593.         FW_CPartPublishIterator iter(fPart);
  594.         for (CTablePublishLink* publisher = (CTablePublishLink*)iter.First(); iter.IsNotComplete(); 
  595.                 publisher = (CTablePublishLink*)iter.Next())
  596.         {
  597.             if (publisher->HasEmbeddedFrame(ev, odEmbeddedFrame))
  598.             {
  599.                 publisher->ContentUpdated(ev, change, FALSE);
  600.                 break;
  601.             }
  602.         }
  603.     }
  604.  
  605.     /* 2) Call ContentUpdated on my display frames as appropriate */
  606.     FW_CPartFrameIterator ite(fPart);
  607.     for (FW_CFrame* frame = ite.First(); ite.IsNotComplete(); frame = ite.Next())
  608.     {
  609.         frame->GetODFrame(ev)->ContentUpdated(ev, change);
  610.     }
  611. }
  612.  
  613. //----------------------------------------------------------------------------------------
  614. //    CTableLinkManager::RevealLink
  615. //----------------------------------------------------------------------------------------
  616.  
  617. void CTableLinkManager::RevealLink(Environment *ev, ODLinkSource* linkSource)
  618. {
  619.     CTablePublishLink* sourceLink = (CTablePublishLink*) ODtoPublishLink(ev, linkSource);
  620.     FW_ASSERT(sourceLink);
  621.  
  622.     // Choose a display frame for the source content
  623.     FW_CFrame* frame = sourceLink->GetFrameToRevealLink(ev);
  624.     if (frame)
  625.     {
  626.         // ----- Activate the frame's window -----
  627.         if (!frame->GetWindow(ev)->IsActive(ev))
  628.             frame->GetWindow(ev)->Select(ev);        
  629.     
  630.         // ----- Activate the frame -----
  631.         if (!frame->IsActive(ev))
  632.         {
  633.             FW_CFrameFacetIterator iter(ev, frame);    // find a facet
  634.             frame->ActivateFrame(ev, iter.First(ev));
  635.         }
  636.  
  637.         // ----- Select the link source -----
  638.         sourceLink->DoSelect(ev, frame);
  639.     }
  640. }
  641.  
  642.  
  643. //----------------------------------------------------------------------------------------
  644. //    CTableLinkManager::IsCellInLink
  645. //----------------------------------------------------------------------------------------
  646. FW_Boolean CTableLinkManager::IsCellInLink(Environment* ev, const CCell& cell)
  647. {
  648.     //--- Check whether the cell participates in any of our source links
  649.     FW_CPartPublishIterator piter(fPart);
  650.     for (CTablePublishLink* publisher = (CTablePublishLink*)piter.First(); piter.IsNotComplete(); 
  651.             publisher = (CTablePublishLink*)piter.Next())
  652.     {
  653.         if (publisher->GetCell(ev) == cell)
  654.             return TRUE;
  655.     }
  656.  
  657.     //--- Check whether the cell participates in any of our destination links
  658.     FW_CPartSubscribeIterator siter(fPart);
  659.     for (CTableSubscribeLink* link = (CTableSubscribeLink*)siter.First(); siter.IsNotComplete(); 
  660.             link = (CTableSubscribeLink*)siter.Next())
  661.     {
  662.         if (link->GetCell(ev) == cell)
  663.             return TRUE;
  664.     }
  665.  
  666.     return FALSE;
  667. }
  668.  
  669. //----------------------------------------------------------------------------------------
  670. // CTableLinkManager::CellToPublishLink
  671. //----------------------------------------------------------------------------------------
  672. CTablePublishLink* CTableLinkManager::CellToPublishLink(Environment* ev, const CCell& cell) const
  673. {
  674.     FW_CPartPublishIterator iter(fPart);
  675.     for (CTablePublishLink* slink = (CTablePublishLink*)iter.First(); iter.IsNotComplete(); 
  676.             slink = (CTablePublishLink*)iter.Next())
  677.     {
  678.         if (slink->GetCell(ev) == cell)
  679.             return slink;
  680.     }
  681.  
  682.     return NULL;
  683. }
  684.  
  685. //----------------------------------------------------------------------------------------
  686. // CTableLinkManager::CellToSubscribeLink
  687. //----------------------------------------------------------------------------------------
  688. CTableSubscribeLink* CTableLinkManager::CellToSubscribeLink(Environment* ev, const CCell& cell) const
  689. {
  690.     FW_CPartSubscribeIterator iter(fPart);
  691.     for (CTableSubscribeLink* link = (CTableSubscribeLink*)iter.First(); iter.IsNotComplete(); 
  692.             link = (CTableSubscribeLink*)iter.Next())
  693.     {
  694.         if (link->GetCell(ev) == cell)
  695.             return link;
  696.     }
  697.  
  698.     return NULL;
  699. }
  700.  
  701. //----------------------------------------------------------------------------------------
  702. // CTableLinkManager::RegisterSubscribers
  703. //----------------------------------------------------------------------------------------
  704.  
  705. void CTableLinkManager::RegisterSubscribers(Environment* ev)
  706. {
  707.     if (this->CountSubscribers(ev) > 0)
  708.     {
  709.         FW_CPartSubscribeIterator iter(fPart);
  710.         for (FW_CSubscribeLink* link = iter.First(); iter.IsNotComplete(); link = iter.Next())
  711.         {
  712.             if (link)
  713.                 link->Register(ev, fPart);
  714.         }
  715.     }
  716. }
  717.  
  718. //----------------------------------------------------------------------------------------
  719. // CTableLinkManager::ShowLinkInfo
  720. //----------------------------------------------------------------------------------------
  721.  
  722. FW_Boolean CTableLinkManager::ShowLinkInfo(Environment* ev, ODFacet* facet)
  723. {
  724.     FW_Boolean handledIt = TRUE;
  725.  
  726.     CTablePublishLink* publisher = this->GetSelectedLinkSource(ev);
  727.     if (publisher)
  728.     {
  729.         CBreakLinkSourceCommand* cmd = publisher->DoLinkInfo(ev, facet);
  730.         if (cmd)
  731.             fPart->ExecuteCommand(ev, (FW_CCommand*)cmd);    // break the link
  732.     }
  733.     else
  734.     {
  735.         CTableSubscribeLink* subscriber = this->GetSelectedLinkDest(ev);
  736.         if (subscriber)
  737.         {
  738.             CBreakLinkCommand* cmd = subscriber->DoLinkInfo(ev, facet);
  739.             if (cmd)
  740.                 fPart->ExecuteCommand(ev, (FW_CCommand*)cmd);    // break the link
  741.         }
  742.         else 
  743.             handledIt = FALSE;
  744.     }
  745.  
  746.     return handledIt;
  747. }
  748.  
  749. //----------------------------------------------------------------------------------------
  750. //    CTableLinkManager::GetSelectedLinkSource
  751. //----------------------------------------------------------------------------------------
  752. CTablePublishLink* CTableLinkManager::GetSelectedLinkSource(Environment* ev)
  753. {
  754.     /* for now, return a link source if its cell is selected */
  755.     CTableSelection* selection = fTablePart->GetTableSelection(ev);
  756.     return this->CellToPublishLink(ev, selection->GetCell());
  757. }
  758.  
  759. //----------------------------------------------------------------------------------------
  760. //    CTableLinkManager::GetSelectedLinkDest
  761. //----------------------------------------------------------------------------------------
  762. CTableSubscribeLink* CTableLinkManager::GetSelectedLinkDest(Environment* ev)
  763. {
  764.     /* for now, return a link if its cell is selected */
  765.     CTableSelection* selection = fTablePart->GetTableSelection(ev);
  766.     return this->CellToSubscribeLink(ev, selection->GetCell());
  767. }
  768.  
  769. //----------------------------------------------------------------------------------------
  770. //    CTableLinkManager::InternalizeOneSourceLink
  771. //---------------------------------------------------------------------------------------
  772.  
  773. void CTableLinkManager::InternalizeOneSourceLink(Environment* ev, 
  774.                                                  ODStorageUnitView* suView,
  775.                                                  ODDraft* suDraft)
  776. {
  777.     ODStorageUnitRef suRef;
  778.     ODUpdateID changeID;
  779.     FW_Boolean validLink = TRUE;
  780.  
  781.     FW_TRY
  782.     {
  783.         FW_CByteArray byteArray;
  784.         suView->GetValue(ev, sizeof(ODStorageUnitRef), byteArray);
  785.         byteArray.CopyBuffer(&suRef, sizeof(ODStorageUnitRef));
  786.         if (suView->IsValidStorageUnitRef(ev, suRef))
  787.         {
  788.             //-- Read the link source data
  789.             ODID linkSourceID = suView->GetIDFromStorageUnitRef(ev, suRef);
  790.             ODLinkSource* odLinkSource = suDraft->AcquireLinkSource(ev, linkSourceID);
  791.             FW_CByteArray ba;
  792.             suView->GetValue(ev, sizeof(ODUpdateID), ba);
  793.             ba.CopyBuffer(&changeID, sizeof(ODUpdateID));
  794.  
  795.             //-- Read the link source's cell
  796.             CCell cell;
  797.             FW_CByteArray ba2;
  798.             suView->GetValue(ev, sizeof(CCell), ba2);
  799.             ba2.CopyBuffer(&cell, sizeof(CCell));
  800.  
  801.             //-- Ensure the link source object references our part as the source of the link
  802.             odLinkSource->SetSourcePart(ev, fTablePart->GetStorageUnit(ev));
  803.  
  804.             //-- Create and add a publisher to represent the link source
  805.             CTablePublishLink* publisher = (CTablePublishLink*)this->NewPublishLink(ev, 
  806.                                                 changeID, fTablePart->fTablePresentation);
  807.             publisher->SetODLinkSource(ev, odLinkSource);
  808.             publisher->SetCell(ev, cell);
  809.             this->AddToPublishLinkList(ev, publisher);
  810.             fTablePart->ChangeFrameStatus(ev, cell, kODInLinkSource);
  811.             odLinkSource->Release(ev);    // to balance AcquireLinkSource above
  812.         }
  813.     }
  814.     FW_CATCH_BEGIN
  815.     FW_CATCH_EVERYTHING()
  816.     {
  817.         validLink = FALSE;
  818.         DebugStr("\pException reading source link in InternalizeOneSourceLink");
  819.         FW_THROW_SAME();
  820.     }
  821.     FW_CATCH_END
  822. }
  823.  
  824. //----------------------------------------------------------------------------------------
  825. //    CTableLinkManager::InternalizeOneDestLink
  826. //---------------------------------------------------------------------------------------
  827.  
  828. void CTableLinkManager::InternalizeOneDestLink(Environment* ev, 
  829.                                                ODStorageUnitView* suView,
  830.                                                ODDraft* suDraft)
  831. {
  832.     //--- Storage unit must already be focussed to a kTableLinkValue value in the kODPropDestLink property
  833.     FW_Boolean validLink = TRUE;
  834.     ODStorageUnitRef suRef;
  835.  
  836.     FW_TRY
  837.     {
  838.         FW_CByteArray byteArray;
  839.         suView->GetValue(ev, sizeof(ODStorageUnitRef), byteArray);
  840.         byteArray.CopyBuffer(&suRef, sizeof(ODStorageUnitRef));
  841.         if (suView->IsValidStorageUnitRef(ev, suRef))
  842.         {
  843.             //-- Read the link data
  844.             ODID linkID = suView->GetIDFromStorageUnitRef(ev, suRef);
  845.             ODLink* odLink = suDraft->AcquireLink(ev, linkID, NULL);
  846.             ODLinkInfo linkInfo;
  847.  
  848.             FW_CByteArray ba;
  849.             suView->GetValue(ev, sizeof(ODLinkInfo), ba);
  850.             ba.CopyBuffer(&linkInfo, sizeof(ODLinkInfo));
  851.             ODType kind = (ODType) FW_CMemoryManager::AllocateBlock((ODULong)linkInfo.kind);    // allocate linkInfo.kind bytes;
  852.  
  853.             FW_CByteArray ba2;
  854.             suView->GetValue(ev, (ODULong)linkInfo.kind, ba2);
  855.             ba2.CopyBuffer((void*)kind, (ODULong)linkInfo.kind);
  856.             linkInfo.kind = kind;
  857.  
  858.             //-- Read the link's cell
  859.             CCell cell;
  860.             FW_CByteArray ba3;
  861.             suView->GetValue(ev, sizeof(CCell), ba3);
  862.             ba3.CopyBuffer(&cell, sizeof(CCell));
  863.  
  864.             //-- Create and add a subscriber to represent the link
  865.             CTableSubscribeLink* subscriber = (CTableSubscribeLink*)this->NewSubscribeLink(ev, 
  866.                                                     odLink, &linkInfo, fTablePart->fTablePresentation);
  867.             subscriber->SetCell(ev, cell);
  868.             this->AddToSubscribeLinkList(ev, subscriber);
  869.             subscriber->HandleSubscribe(ev);
  870.             odLink->Release(ev);    // to balance AcquireLink above
  871.         }
  872.     }
  873.     FW_CATCH_BEGIN
  874.     FW_CATCH_EVERYTHING()
  875.     {
  876.         validLink = FALSE;
  877.         DebugStr("\pException reading dest link in InternalizeOneDestLink");
  878.         FW_THROW_SAME();
  879.     }
  880.     FW_CATCH_END
  881. }
  882.  
  883. //----------------------------------------------------------------------------------------
  884. //    CTableLinkManager::UpdateLinkSource
  885. //----------------------------------------------------------------------------------------
  886.  
  887. void CTableLinkManager::UpdateLinkSource(Environment* ev, ODUpdateID updateID)
  888. {
  889.     CTablePublishLink* linkSource = this->GetSelectedLinkSource(ev);
  890.     if (linkSource)
  891.         linkSource->ContentUpdated(ev, updateID, TRUE);
  892. }
  893.  
  894. //----------------------------------------------------------------------------------------
  895. //    CTableLinkManager::BreakExistingLinks
  896. //----------------------------------------------------------------------------------------
  897. void CTableLinkManager::BreakExistingLinks(Environment* ev, const CCell& cell)
  898. {
  899.     //-- Check for a link being broken --
  900.     CTablePublishLink* linkSource = this->CellToPublishLink(ev, cell);
  901.     if (linkSource)
  902.     {
  903.         this->BreakPublishLink(ev, linkSource);
  904.         delete linkSource;
  905.     }
  906.     CTableSubscribeLink* link = this->CellToSubscribeLink(ev, cell);
  907.     if (link)
  908.     {
  909.         this->BreakSubscribeLink(ev, link);
  910.         delete link;
  911.     }
  912. }
  913.  
  914. //----------------------------------------------------------------------------------------
  915. //    CTableLinkManager::MoveExistingLinks
  916. //----------------------------------------------------------------------------------------
  917. void CTableLinkManager::MoveExistingLinks(Environment* ev,
  918.                                           const CCell& fromCell,
  919.                                           const CCell& toCell)
  920. {
  921.     //-- Adjust affected links --
  922.     CTablePublishLink* slink = this->CellToPublishLink(ev, fromCell);
  923.     if (slink)
  924.         slink->SetCell(ev, toCell);
  925.     CTableSubscribeLink* link = this->CellToSubscribeLink(ev, fromCell);
  926.     if (link)
  927.         link->SetCell(ev, toCell);
  928. }
  929.  
  930. //------------------------------------------------------------------------------
  931. // CTableLinkManager::ExternalizeLinks
  932. //------------------------------------------------------------------------------
  933. void CTableLinkManager::ExternalizeLinks(Environment* ev, ODStorageUnitView* suView,
  934.                                          FW_CCloneInfo* cloneInfo)
  935. {
  936.     ODStorageUnit* su = suView->GetStorageUnit(ev);
  937.  
  938.     //--- Write out the source links ---
  939.     if (this->CountPublishers(ev) > 0)
  940.     {
  941.         //-- Make sure the correct property and value is present in the SU --
  942.         FW_SUForceFocus(ev, su, kODPropSourceLink, kTableLinkValue);
  943.  
  944.         FW_CPartPublishIterator iter(fPart);
  945.         for (CTablePublishLink* slink = (CTablePublishLink*)iter.First(); iter.IsNotComplete(); 
  946.                 slink = (CTablePublishLink*)iter.Next())
  947.         {
  948.             slink->Externalize(ev, su, cloneInfo);
  949.         }
  950.     }
  951.     else
  952.         FW_SURemoveProperty(ev, su, kODPropSourceLink);
  953.  
  954.     //--- Write out the destination links ---
  955.     if (this->CountSubscribers(ev) > 0)
  956.     {
  957.         //-- Make sure the correct property and value is present in the SU --
  958.         FW_SUForceFocus(ev, su, kODPropDestLink, kTableLinkValue);
  959.  
  960.         FW_CPartSubscribeIterator iter(fPart);
  961.         for (CTableSubscribeLink* link = (CTableSubscribeLink*)iter.First(); iter.IsNotComplete(); 
  962.                 link = (CTableSubscribeLink*)iter.Next())
  963.         {
  964.             link->Externalize(ev, su, cloneInfo);
  965.         }
  966.     }
  967.     else
  968.         FW_SURemoveProperty(ev, su, kODPropDestLink);
  969. }
  970.  
  971. //------------------------------------------------------------------------------
  972. // CTableLinkManager::InternalizeLinks
  973. //------------------------------------------------------------------------------
  974. void CTableLinkManager::InternalizeLinks(Environment* ev, ODStorageUnit* storageUnit)
  975. {
  976.     unsigned long offsetLimit;
  977.  
  978.     if (storageUnit->Exists(ev, kODPropSourceLink, kTableLinkValue, 0))
  979.     {
  980.         storageUnit->Focus(ev, kODPropSourceLink, kODPosUndefined, kTableLinkValue, 0, kODPosUndefined);
  981.         ODStorageUnitView* suView = storageUnit->CreateView(ev);
  982.         offsetLimit = suView->GetSize(ev);
  983.  
  984.         while (suView->GetOffset(ev) < offsetLimit)
  985.         {
  986.             InternalizeOneSourceLink(ev, suView, storageUnit->GetDraft(ev));
  987.         }
  988.         delete suView;
  989.     }
  990.  
  991.     if (storageUnit->Exists(ev, kODPropDestLink, kTableLinkValue, 0))
  992.     {
  993.         storageUnit->Focus(ev, kODPropDestLink, kODPosUndefined, kTableLinkValue, 0, kODPosUndefined);
  994.         ODStorageUnitView* suView = storageUnit->CreateView(ev);
  995.         offsetLimit = suView->GetSize(ev);
  996.  
  997.         while (suView->GetOffset(ev) < offsetLimit)
  998.         {
  999.             InternalizeOneDestLink(ev, suView, storageUnit->GetDraft(ev));
  1000.         }
  1001.         delete suView;
  1002.     }
  1003. }
  1004.  
  1005.